#include <iostream>
#include <unistd.h>
#include "Mutex.hpp"

using namespace MutexModule;

int ticket = 1000;

// 封装一个线程信息对象，描述线程的名字，以及线程持有的锁
class ThreadData
{
public:
    ThreadData(const std::string &name, Mutex &lock)
        : _name(name),
          _lockp(&lock)
    {
    }
    ~ThreadData()
    {
    }
    std::string _name;
    Mutex *_lockp;
};

void *routine(void *args)
{
    ThreadData *td = static_cast<ThreadData *>(args);

    while (true)
    {
        {
            //  临界区
            LockGuard guard(*(td->_lockp)); // 这里是LockGuard类型的临时对象，当跳出该代码块的是会调用其析构函数释放锁
                                            // 这个叫做RAII风格的互斥锁
            if (ticket > 0)
            {
                usleep(1000);
                printf("%s sells ticket:%d\n", td->_name.c_str(), ticket);
                ticket--;
            }
            else
            {
                break;
            }
        }

        usleep(1000);
    }

    return nullptr;
}

int main()
{
    // 1. 调用Mutex的构造函数，创建一个局部的互斥量对象lock
    Mutex lock;
    pthread_t t1, t2, t3, t4;

    // 2. 分别给每个线程创建一个ThreadData对象，用于表示每个线程的名字信息
    //    每个线程的锁是传的引用，所以四个线程的锁是同一个锁
    ThreadData *td1 = new ThreadData("thread 1", lock);
    pthread_create(&t1, nullptr, routine, td1);

    ThreadData *td2 = new ThreadData("thread 2", lock);
    pthread_create(&t2, nullptr, routine, td2);

    ThreadData *td3 = new ThreadData("thread 3", lock);
    pthread_create(&t3, nullptr, routine, td3);

    ThreadData *td4 = new ThreadData("thread 4", lock);
    pthread_create(&t4, nullptr, routine, td4);

    pthread_join(t1, nullptr);
    pthread_join(t2, nullptr);
    pthread_join(t3, nullptr);
    pthread_join(t4, nullptr);

    return 0;
}

// // 封装一个线程信息对象，描述线程的名字，以及线程持有的锁
// class ThreadData
// {
// public:
//     ThreadData(const std::string &name, Mutex& lock)
//         : _name(name),
//           _lockp(&lock)
//     {
//     }
//     ~ThreadData()
//     {
//     }
//     std::string _name;
//     Mutex *_lockp;
// };

// void* routine(void *args)
// {
//     ThreadData* td = static_cast<ThreadData*>(args);

//     while(true)
//     {
//         td->_lockp->Lock();
//         if (ticket > 0)
//         {
//             usleep(1000);
//             printf("%s sells ticket:%d\n", td->_name.c_str(), ticket);
//             ticket--;
//             td->_lockp->Unlock();
//         }
//         else
//         {
//             td->_lockp->Unlock();
//             break;
//         }
//     }

//     return nullptr;
// }

// int main()
// {
//     // 1. 调用Mutex的构造函数，再堆上创建一个局部的互斥量对象lock
//     Mutex lock;
//     pthread_t t1, t2, t3, t4;

//     // 2. 分别给每个线程创建一个ThreadData对象，用于表示每个线程的名字信息
//     //    每个线程的锁是传的引用，所以四个线程的锁是同一个锁
//     ThreadData* td1 = new ThreadData("thread 1", lock);
//     pthread_create(&t1, nullptr, routine, td1);

//     ThreadData* td2 = new ThreadData("thread 2", lock);
//     pthread_create(&t2, nullptr, routine, td2);

//     ThreadData* td3 = new ThreadData("thread 3", lock);
//     pthread_create(&t3, nullptr, routine, td3);

//     ThreadData* td4 = new ThreadData("thread 4", lock);
//     pthread_create(&t4, nullptr, routine, td4);

//     pthread_join(t1, nullptr);
//     pthread_join(t2, nullptr);
//     pthread_join(t3, nullptr);
//     pthread_join(t4, nullptr);

//     return 0;
// }